﻿using System;
using System.Security.Principal;
using System.Web;
using System.Web.Security;
using Newtonsoft.Json;

namespace SpeadFrm.Web.FormsAuth
{
    public class FormsPrincipal<TUserData> : IPrincipal where TUserData : class,new()
    {
        private readonly IIdentity _identity;
        private readonly TUserData _userData;

        public FormsPrincipal(FormsAuthenticationTicket ticket, TUserData userData)
        {
            if (ticket == null)
                throw new ArgumentNullException("ticket");
            if (userData == null)
                throw new ArgumentNullException("userData");

            _identity = new FormsIdentity(ticket);
            _userData = userData;

        }

        public TUserData UserData
        {
            get { return _userData; }
        }

        public bool IsInRole(string role)
        {
            var principal = _userData as IPrincipal;
            if (principal == null)
                throw new NotImplementedException();
            return principal.IsInRole(role);
        }

        public IIdentity Identity
        {
            get { return _identity; }
        }

        public static void Sign(string loginName, TUserData userData, bool isPersistent, int expiration)
        {
            if (string.IsNullOrEmpty(loginName))
                throw new ArgumentNullException("loginName");
            if (userData == null)
                throw new ArgumentNullException("userData");

            var data = JsonConvert.SerializeObject(userData);
            var ticket = new FormsAuthenticationTicket(2, loginName, DateTime.Now, DateTime.Now.AddDays(1), isPersistent, data);
            var cookieValue = FormsAuthentication.Encrypt(ticket);
            var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, cookieValue)
                             {
                                 HttpOnly = true,
                                 Secure = FormsAuthentication.RequireSSL,
                                 Domain = FormsAuthentication.CookieDomain,
                                 Path = FormsAuthentication.FormsCookiePath,
                             };
            if (expiration > 0)
                cookie.Expires = DateTime.Now.AddMinutes(expiration);

            var context = HttpContext.Current;
            if (context == null)
                throw new InvalidOperationException();

            context.Response.Cookies.Remove(cookie.Name);
            context.Response.Cookies.Add(cookie);
        }

        public static void TrySetUserInfo(HttpContext context)
        {
            if (context == null) throw new InvalidOperationException();
            var cookie = context.Request.Cookies[FormsAuthentication.FormsCookieName];
            if (cookie == null || string.IsNullOrEmpty(cookie.Value))
                return;

            try
            {
                TUserData userData = null;
                // 2. 解密Cookie值，获取FormsAuthenticationTicket对象
                var ticket = FormsAuthentication.Decrypt(cookie.Value);

                if (ticket != null && string.IsNullOrEmpty(ticket.UserData) == false)
                    userData = JsonConvert.DeserializeObject<TUserData>(ticket.UserData);

                if (ticket != null && userData != null)
                    context.User = new FormsPrincipal<TUserData>(ticket, userData);
            }
            catch
            { 
            }
        }
    }
}